#pragma once

#include "zen_macro.h"
#include "console_tester.h"

////////////////////////////////////////
#include "zen_ascii.h"
void debug_ascii()
{
	using std::cout;
	using std::endl;

	for (int i = 0; i <= 9; ++i)
	{
		cout << "ASCII_DEFINE(Num" << i << std::hex << ", 0x" << '0' + i << ")" << endl;
	}
	cout << endl;
	for (int i = 'a'; i <= 'z'; ++i)
	{
		cout << "ASCII_DEFINE(Lower" << char(i + 'A' - 'a') << ", 0x" << std::hex << i << ")" << endl;
	}
	cout << endl;
	for (int i = 'A'; i <= 'Z'; ++i)
	{
		cout << "ASCII_DEFINE(Cap" << char(i) << ", 0x" << std::hex << i << ")" << endl;
	}
	cout << std::dec;
}

AddTestQ(ascii);

////////////////////////////////////////
#include "zen_log.h"
void debug_log()
{
	Zen::LogD("This's the %s, called by function %s in the file %s:%d", "log-debug", __FUNCTION__, __FILE__, __LINE__);
	Zen::LogE("This is error log, error no is %d, file:%s", 0, __FILENAME__);
	__Trace(1);
	__Trace(0);
	__TraceString("This is trace string.");
}
AddTestQ(log);

////////////////////////////////////////
#include "zen_class.h"
class TestClass
{
	ZEN_GET_SET_COPY(int, _P1, GetP1, SetP1){};
	ZEN_GET_SET_REF(int, _P2, GetP2, SetP2){};
	ZEN_GET_COPY(int, _P3, GetP3){};
	ZEN_GET_REF(int, _P4, GetP4){};
};
void debug_class()
{
	TestClass tc;
	tc.SetP1(10);
	tc.SetP2(20);
	PRINTER(tc.GetP1(), tc.GetP2(), tc.GetP3());
}
AddTestQ(class);

////////////////////////////////////////
#include "zen_error.h"
Zen::Error<int> GoError()
{
	return 2;
}
void debug_error()
{
	auto e = GoError();
	auto s = std::move(e);
	PRINTER("error:", s.GetCode());
	GoError();
}
AddTestQ(error);

////////////////////////////////////////
#include "zen_print.h"
void debug_print()
{
	using namespace Zen;

	cout << R"(Printer{char(0x20)}(1, 2, 3, 4, "hello");)" << endl;
	Printer<char>{ char(0x20), 10 }(1, 2, 3, 4, "hello");

	cout << R"(PRINTER(1, 2, 3, 4, "hello");)" << endl;
	PRINTER(1, 2, 3, 4, "hello");

	cout << R"(Printer{std::string(1, 0x20)}(1, 2, 3, 4, "hello");)" << endl;
	Printer<std::string>{ std::string(1, 0x20), {} }(1, 2, 3, 4, "hello");

	cout << R"(Printer{char(0)}("tab", (int)Ascii::Tab);)" << endl;
	Printer<char>{ 0, 0 }("tab", (int)Ascii::Tab);

	cout << R"(Printer{0}("ret", (int)Ascii::NewLine);)" << endl;
	Printer<char>{ 0, 0 }("ret", (int)Ascii::NewLine);

	cout << R"(Printer{"..."})" << endl;
	auto m = std::map<int, std::string>{ { 1, "Jim" }, { 2, "Tom" } };

	Printer<std::string>{ "...", "" }("Hello", "world", 123, m, std::vector<int>{ 0, 1, 2, 3 });

	std::stringstream ss;
	Printer<std::string>{ " ", "", ss }(1, 2, 3, 4, 5, 6);
	std::string str;
	ss >> str;
	ss.clear();
	cout << ss.str() << endl;

	cout << "ToString" << endl;
	cout << ToString("Hello", "world", 123, m, std::vector<int>{ 0, 1, 2, 3 }) << endl;
}
AddTestQ(print);

////////////////////////////////////////
#include "zen_exception.h"
void debug_exception()
{
	int n = 20;
	do
	{
		int r = ::rand() % 3;
		try
		{
			if (r == 0)
			{
				__zen_must(0);
			} else if (r == 1)
			{
				__zen_must_else(0, "exception~");
			} else
			{
				PRINTER("no e");
			}
		} catch (Zen::Exception& e)
		{
			PRINTER(r, e.what());
		}
	} while (--n);
}
AddTestQ(exception);

////////////////////////////////////////
#include "zen_wrap.h"

template <typename T>
int64_t test_wrap(int count)
{
	T t{};
	for (int i = 0; i < count; ++i)
	{
		t += i;
		t *= 4;
		t /= 2;
		t <<= 2;
		t >>= 1;
		t -= 3;
		t = t * t;
	}
	return t;
}
template <typename T1, typename T2>
void compare_wrap(int n)
{
	auto sa = test_wrap<T1>(n);
	auto na = test_wrap<T2>(n);
	PRINTER(sa, na);
}

void debug_wrap()
{
	compare_wrap<Zen::Int8s, int8_t>(1000);
	compare_wrap<Zen::Int32s, int32_t>(1000);
	compare_wrap<Zen::Int64s, int64_t>(100000);
}
AddTestQ(wrap);
